package
{
	import flash.display.Sprite;
	import flash.events.*;
	
	/** This class creates an object of discrete color choices that can be picked */
	public class ColorPicker extends Sprite
	{
		public const HUE_COUNT:uint = 24;
		public const SATURATION_COUNT:uint = 7;
		// public vars
		public var WIDTH:Number, HEIGHT:Number;
		// private objs
		private var colors:Array; // a 2d array of colors, outside is number of Saturations, inside is number of HUES
		private var colorSprites:Array;
		private var currentSprite:Sprite;
		private var _color:uint;
		public function get color():uint{return _color;}
		
		public function ColorPicker(WIDTH:Number=0, HEIGHT:Number=0)
		{
			this.WIDTH = WIDTH;
			this.HEIGHT = HEIGHT;
			this.addEventListener(Event.ADDED, handleAdded);
		}
		private function handleAdded (event:Event):void
		{
			this.removeEventListener(Event.ADDED, handleAdded);
			this.addEventListener(Event.REMOVED, handleRemoved);
			if (WIDTH > 0 && HEIGHT > 0)
			{
				
			} if (WIDTH > 0)
			{
				HEIGHT = WIDTH * SATURATION_COUNT / HUE_COUNT;
			} else if (HEIGHT > 0)
			{
				WIDTH = HEIGHT * HUE_COUNT / SATURATION_COUNT;
			} else 
			{
				WIDTH = parent.width;
				HEIGHT = WIDTH * SATURATION_COUNT / HUE_COUNT;
			}
			this.graphics.beginFill(0x000000);
			this.graphics.drawRect(0, 0, WIDTH, HEIGHT);
			this.graphics.endFill();
			
			// CREATE COLORS
			/// (r,g,b)
			/// (255, 0, 0) -> (255, 255, 0) -> (0, 255, 0) -> (0, 255, 255) -> (0, 0, 255) -> (255, 0, 255)
			
			
			colors = new Array();	
			var max_sat:int = -1;
			var min_sat:int = 0;
			for (var s:uint=0; s < SATURATION_COUNT; s++)
			{
				// we reached full saturation
				if (max_sat == 255)	{ min_sat += 256/((SATURATION_COUNT+1)/2);}
				
				if (max_sat < 255){ max_sat += 256/((SATURATION_COUNT+1)/2);}
				else if (max_sat > 255) {max_sat = 255;}
				
				//trace(min_sat, max_sat);
				
				var reds:Int = new Int(max_sat);
				var greens:Int = new Int(min_sat);
				var blues:Int = new Int(min_sat);
				var color:uint;
				var color1:Int = reds;
				var color2:Int = greens;
				var color3:Int = blues;
				var colort:Int;
				var dir:int = 1; // are we increasing or decreasing color 2?
				
				var hues:Array = new Array();
				for (var h:uint=0; h < HUE_COUNT; h++)
				{
					color = reds.value << 16 | greens.value << 8 | blues.value;
					hues.push(color);
					//if(s==0)trace(dir, reds.value, greens.value, blues.value, color, color2.value + dir * (max_sat+1) / (HUE_COUNT / 6));
					if (color2.value == max_sat) color2.value = max_sat+1;
					color2.value += dir * ((max_sat+1)-min_sat) / (HUE_COUNT / 6);
					if (color2.value >= (max_sat+1))
					{
						color2.value = max_sat;
						color1.value = max_sat;
						dir = -1;
						// switch color1 and color2, leave color3
						colort = color1;
						color1 = color2;
						color2 = colort;
					} else if (color2.value <= min_sat)
					{
						color2.value = min_sat;
						dir = 1;
						// switch color2 with color3, leave color 1
						colort = color2;
						color2 = color3;
						color3 = colort;					
					}
				}
				colors.push(hues);
			}
			drawColors();
		}
		
		public function drawColors ():void
		{
			if (colorSprites == null)
			{
				colorSprites = new Array();
			} else 
			{
				for each (var cs:Sprite in colorSprites)
				{
					this.removeChild(cs);
				}
			}
			for (var i:uint=0; i < colors.length; i++)
			{
				var arr:Array = colors[i];
				for (var j:uint=0; j < arr.length; j++)
				{
					var colorSprite:Sprite = new Sprite();
					colorSprite.name = String(arr[j]);
					colorSprite.graphics.beginFill(arr[j]);
					colorSprite.graphics.drawRect(0, 0, this.width/arr.length, this.height/colors.length);
					colorSprite.graphics.endFill();
					colorSprite.x = j * this.width/arr.length;
					colorSprite.y = i * this.height/colors.length;
					colorSprite.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOverSprite);
					this.addChild(colorSprite);
					colorSprites.push(colorSprite);
				}
			}
		}
		private function handleMouseOverSprite(event:MouseEvent):void
		{
			currentSprite = Sprite(event.currentTarget);
			_color = uint(currentSprite.name);
			currentSprite.addEventListener(MouseEvent.CLICK, handleClickSprite);
			currentSprite.addEventListener(MouseEvent.MOUSE_OUT, handleMouseOutSprite);
			//trace("color", color);
		}
		private function handleMouseOutSprite (event:MouseEvent):void
		{
			currentSprite.removeEventListener(MouseEvent.CLICK, handleClickSprite);
			currentSprite.removeEventListener(MouseEvent.MOUSE_OUT, handleMouseOutSprite);
			currentSprite.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOverSprite);
			currentSprite = null;
			_color = 0xFFFFFF;
		}
		private function handleClickSprite (event:MouseEvent):void
		{
			//trace("click");
			this.dispatchEvent(new Event(Event.COMPLETE));
		}
		private function handleRemoved(event:Event):void
		{
			this.removeEventListener(Event.REMOVED, handleRemoved);
			if (currentSprite != null)
			{
				currentSprite.removeEventListener(MouseEvent.CLICK, handleClickSprite);
				currentSprite.removeEventListener(MouseEvent.MOUSE_OUT, handleMouseOutSprite);
			}
			for each (var cs:Sprite in colorSprites)
			{
				if (cs.hasEventListener(MouseEvent.MOUSE_OVER)) cs.removeEventListener(MouseEvent.MOUSE_OVER, handleMouseOverSprite);
			}
		}
	}
}